﻿using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;

namespace SBPweb.PROvibe.Server.Library.Hosting
{

    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.High)]
    public class CustomServiceVirtualPathProvider : VirtualPathProvider
    {

        public const string VirtualWcfDirectoryName = "~/Services/Dynamic";
                
        public override string CombineVirtualPaths(string basePath, string relativePath)
        {
            return Previous.CombineVirtualPaths(basePath, relativePath);
        }

        public override bool FileExists(string virtualPath)
        {
            string appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);

            if (IsVirtualFile(appRelativeVirtualPath))
            {
                return true;
            }
            else
            {
                return Previous.FileExists(virtualPath);
            }
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            string appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);

            if (IsVirtualFile(appRelativeVirtualPath))
            {
                return new WcfVirtualFile(virtualPath);
            }
            else
            {
                return Previous.GetFile(virtualPath);
            }
        }

        public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            string appRelativeVirtualPath = ToAppRelativeVirtualPath(virtualPath);
            if (IsVirtualFile(appRelativeVirtualPath) || IsVirtualDirectory(appRelativeVirtualPath))
            {
                return null;
            }
            else
            {
                return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
            }
        }

        private bool IsVirtualFile(string appRelativeVirtualPath)
        {
            if (appRelativeVirtualPath.StartsWith(VirtualWcfDirectoryName + "/", StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
            return false;
        }

        private bool IsVirtualDirectory(string appRelativeVirtualPath)
        {
            return appRelativeVirtualPath.Equals(VirtualWcfDirectoryName, StringComparison.OrdinalIgnoreCase);
        }

        private string ToAppRelativeVirtualPath(string virtualPath)
        {
            string appRelativeVirtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
            if (!appRelativeVirtualPath.StartsWith("~/"))
            {
                throw new HttpException("Unexpectedly does not start with ~.");
            }
            return appRelativeVirtualPath;
        }

    }

    public class WcfVirtualFile : VirtualFile
    {
        
        public WcfVirtualFile(string vp)
            : base(vp)
        {
        }

        public override Stream Open()
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter tw = new StreamWriter(stream);
            tw.Write(string.Format(CultureInfo.InvariantCulture, "<%@ServiceHost language=c# Debug=\"true\" Factory=\"{0}\"%>", HttpUtility.HtmlEncode(typeof(CustomServiceHostFactory).FullName)));
            tw.Flush();
            stream.Position = 0;
            return stream;
        }

    }

}